module ActiveBackground
  # MiddleMan Proxy is a class that makes sure that calls passed to
  # MiddleMan are processed. Making sure that there is a connection
  # established or commands are cached till the server comes back.
  class MiddleManProxy
    include Singleton
    
    attr_reader :messages
    attr_accessor :context

    def initialize
      @context=nil
    end
    
    # Context is the object that the commands are passed to by both the
    # Server and Client applications. ActiveBackground::Initializer passes
    # the MiddleMan instance. 
    # 
    #   <b>NOTE: Please do not pass a different context unless you know what you are doing.</b>
    # 
    # Arguments:
    #   <tt>context:</tt>
    #   
    def context(context=nil)
      if context
        @context=context
      else
        @context
      end
    end
    alias :context= :context
    
    private
      # methods call to the Proxy are passed to the context
      def method_missing(method, *args, &block)
        # connect or get cache object to process commands
        @context.prepare() unless [:register].include?(method.to_sym)
        # call the method and pass the arguments and block (if supplied)
        @logger = ActiveBackground::Configuration.instance.logger
        @logger.info("MiddleManProxy: Calling #{method.to_s}")
        @logger.debug("MiddleManProxy: #{method.to_s} with #{args.inspect} and #{block.inspect}")
        @context.send(method, *args, &block)
      end
  end
  
  # MiddleMan is responsible to communicate between application and
  # the Server. All internal processing (like falling back to slave
  # servers, redirect to LocalCache, or pushing to backup server).
  # 
  # == Handlers
  # 
  # MiddleMan allow you to registers handlers that can extend MiddleMan
  # behavior. Handlers should only handle initialization, preprocessing
  # of jobs, and pushing the job to MiddleMan. Default handlers are
  # chef (allows to initialize jobs from defined load paths) and cache
  # that allows you to store values on server.
  # 
  # Handlers need to be in the ActiveBackground module space, like
  # ActiveBackground::Chef.
  # 
  #   register(ActiveBackground::Chef.new)
  #   
  # and then you can use the handlers with
  # 
  #   MiddleMan.chef.do_something
  #   
  # == Job
  # 
  # * finders
  # * job manipulation
  #   
  class MiddleMan < Client
      
    def initialize
      @handler = Hash.new
    end
    
    # TODO: Add some checking if the handler has all the expected methods
    def register(handler)
      unless @handler[(handler.class.to_s.split("::")[2]).downcase.to_sym]
        @handler[(handler.class.to_s.split("::")[2]).downcase.to_sym] = handler
      end
    end
    
    # TODO: Need to raise and error if handler doesn't exist
    def method_missing(method, *args)
      return @handler[method.to_sym] if @handler[method.to_sym]
    end
    
    def server
      @@server
    end
    
    def server_terminate
      @@server.terminate
    end
    
    def server_wait
      @@server.wait if @@server
    end
  end
end